package com.zchat.api;

import java.util.Map;

import org.jivesoftware.smack.ConnectionConfiguration;
import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smack.provider.PrivacyProvider;
import org.jivesoftware.smack.provider.ProviderManager;
import org.jivesoftware.smackx.GroupChatInvitation;
import org.jivesoftware.smackx.PrivateDataManager;
import org.jivesoftware.smackx.bytestreams.socks5.provider.BytestreamsProvider;
import org.jivesoftware.smackx.packet.ChatStateExtension;
import org.jivesoftware.smackx.packet.LastActivity;
import org.jivesoftware.smackx.packet.OfflineMessageInfo;
import org.jivesoftware.smackx.packet.OfflineMessageRequest;
import org.jivesoftware.smackx.packet.SharedGroupsInfo;
import org.jivesoftware.smackx.provider.AdHocCommandDataProvider;
import org.jivesoftware.smackx.provider.DataFormProvider;
import org.jivesoftware.smackx.provider.DelayInformationProvider;
import org.jivesoftware.smackx.provider.DiscoverInfoProvider;
import org.jivesoftware.smackx.provider.DiscoverItemsProvider;
import org.jivesoftware.smackx.provider.MUCAdminProvider;
import org.jivesoftware.smackx.provider.MUCOwnerProvider;
import org.jivesoftware.smackx.provider.MUCUserProvider;
import org.jivesoftware.smackx.provider.MessageEventProvider;
import org.jivesoftware.smackx.provider.MultipleAddressesProvider;
import org.jivesoftware.smackx.provider.RosterExchangeProvider;
import org.jivesoftware.smackx.provider.StreamInitiationProvider;
import org.jivesoftware.smackx.provider.VCardProvider;
import org.jivesoftware.smackx.provider.XHTMLExtensionProvider;
import org.jivesoftware.smackx.search.UserSearch;

import android.content.Context;
import android.util.Log;

import com.zchat.android.WelcomeActivity;
import com.zchat.android.provider.DBHelper;
import com.zchat.android.provider.DBHelperImpl;
import com.zchat.api.cache.Cache;
import com.zchat.api.cache.CacheManagerImple;
import com.zchat.api.log.Logger;
import com.zchat.api.modules.Module;
import com.zchat.api.modules.ModuleManager;
import com.zchat.api.modules.ModuleManagerImple;
import com.zchat.api.modules.test.TestModule;
import com.zchat.api.util.ZChatSetting;


/**
 * 
 * @author Oliverzhu
 *	2012/6/12
 */
public class ZChat {
	private static final String TAG="ZChat";
	public static final boolean DEBUG = ZChatSetting.DEBUG;
	
	private Context context;
	
	public static final String AUTHORITY="com.zchat.android.provider.DBContentProvider";
	
	/** 服务器域名 */
	public static final String ZCHAT_DOMAIN = "xxx.com";
	
	/** 服务器地址 */
	public static final String ZCHAT_SERVER = "http://xxx.xxxx.com";
	
	/** 主机地址 */
	public static final String ZCHAT_HOST = "192.168.1.56";
	
	/** 主机端口号*/
	public static final int ZCHAT_PORT = 5222;
	
	private ZChatHttpApi mHttpApi;
	
	private ModuleManager moduleManager;
	
	private  XMPPConnection connection;
	
	public ZChat(ZChatHttpApi httpApi)
	{
		mHttpApi = httpApi;
		moduleManager = ModuleManagerImple.getInstance();
	}
	
	public ZChat(XMPPConnection conn)
	{
		this.connection = conn;
		moduleManager = ModuleManagerImple.getInstance();
	}
	
	public static final XMPPConnection creatXMPPConnection(String host,int port)
	{
		ConnectionConfiguration connectionConfig = new ConnectionConfiguration(
				host, port, "");
		
		connectionConfig.setSASLAuthenticationEnabled(false);
		XMPPConnection connection = new XMPPConnection(connectionConfig);


		ProviderManager pm = ProviderManager.getInstance();
		configure(pm);
		
		return connection;
	}
	
	public void setContext(Context context)
	{
		this.context = context;
	}
	
    /** 测试服务器 */
    public static final ZChatHttpApi createHttpApi(String domain, String clientVersion,
            boolean useOAuth) {
        if(DEBUG) Logger.info(TAG+"-createHttpApi");
        return new ZChatHttpApi(domain, clientVersion, useOAuth);
    }
    
    /** 正式服务器 */
    public static final ZChatHttpApi createHttpApi(String clientVersion, boolean useOAuth) {
        return createHttpApi(ZCHAT_DOMAIN, clientVersion, useOAuth);
    }
    
    public void openXMPPConnection()
    {
    	try {
			connection.connect();
		} catch (XMPPException e) {
			e.printStackTrace();
		}
    }
    
    public boolean isXMPPConnected()
    {
    	return connection.isConnected();
    }
    
    public boolean isAuthenticated(String userName,String userPassword)
    {
    	try {
			connection.login(userName, userPassword);
		} catch (XMPPException e) {
			e.printStackTrace();
		}
    	return connection.isAuthenticated();
    }
    
    
    public XMPPConnection getXMPPConnection()
    {
    	return connection;
    }
    
    public void closeXMPPConnection()
    {
    	if(connection.isConnected())
    	{
    		connection.disconnect();
    	}
    }
    
    /**
     * 获得缓存管理
     * @return
     */
    public static Cache getCache()
    {
    	return CacheManagerImple.getInstance();
    }
    
    /**
     * 获得模块管理器
     * @return
     */
    public ModuleManager getModuleManager()
    {
    	return moduleManager;
    }
    /**
     * 获得测试数据
     * @return
     */
    public Map<String, Object> getTestDatas()
    {
    	TestModule testModule = 
    			(TestModule) moduleManager.getModule(TestModule.class);
    	
    	return testModule.receiveData(context);
    	
    }
    
    private static void configure(ProviderManager pm) {

		// Private Data Storage
		pm.addIQProvider("query", "jabber:iq:private",
				new PrivateDataManager.PrivateDataIQProvider());

		// Time
		try {
			pm.addIQProvider("query", "jabber:iq:time", Class
					.forName("org.jivesoftware.smackx.packet.Time"));
		} catch (ClassNotFoundException e) {
			Log.w("TestClient",
					"Can't load class for org.jivesoftware.smackx.packet.Time");
		}

		// Roster Exchange
		pm.addExtensionProvider("x", "jabber:x:roster",
				new RosterExchangeProvider());

		// Message Events
		pm.addExtensionProvider("x", "jabber:x:event",
				new MessageEventProvider());

		// Chat State
		pm.addExtensionProvider("active",
				"http://jabber.org/protocol/chatstates",
				new ChatStateExtension.Provider());

		pm.addExtensionProvider("composing",
				"http://jabber.org/protocol/chatstates",
				new ChatStateExtension.Provider());

		pm.addExtensionProvider("paused",
				"http://jabber.org/protocol/chatstates",
				new ChatStateExtension.Provider());

		pm.addExtensionProvider("inactive",
				"http://jabber.org/protocol/chatstates",
				new ChatStateExtension.Provider());

		pm.addExtensionProvider("gone",
				"http://jabber.org/protocol/chatstates",
				new ChatStateExtension.Provider());

		// XHTML
		pm.addExtensionProvider("html", "http://jabber.org/protocol/xhtml-im",
				new XHTMLExtensionProvider());

		// Group Chat Invitations
		pm.addExtensionProvider("x", "jabber:x:conference",
				new GroupChatInvitation.Provider());

		// Service Discovery # Items
		pm.addIQProvider("query", "http://jabber.org/protocol/disco#items",
				new DiscoverItemsProvider());

		// Service Discovery # Info
		pm.addIQProvider("query", "http://jabber.org/protocol/disco#info",
				new DiscoverInfoProvider());

		// Data Forms
		pm.addExtensionProvider("x", "jabber:x:data", new DataFormProvider());

		// MUC User
		pm.addExtensionProvider("x", "http://jabber.org/protocol/muc#user",
				new MUCUserProvider());

		// MUC Admin
		pm.addIQProvider("query", "http://jabber.org/protocol/muc#admin",
				new MUCAdminProvider());

		// MUC Owner
		pm.addIQProvider("query", "http://jabber.org/protocol/muc#owner",
				new MUCOwnerProvider());

		// Delayed Delivery
		pm.addExtensionProvider("x", "jabber:x:delay",
				new DelayInformationProvider());

		// Version
		try {
			pm.addIQProvider("query", "jabber:iq:version", Class
					.forName("org.jivesoftware.smackx.packet.Version"));
		} catch (ClassNotFoundException e) {
			// Not sure what's happening here.
		}
		// VCard
		pm.addIQProvider("vCard", "vcard-temp", new VCardProvider());

		// Offline Message Requests
		pm.addIQProvider("offline", "http://jabber.org/protocol/offline",
				new OfflineMessageRequest.Provider());

		// Offline Message Indicator
		pm.addExtensionProvider("offline",
				"http://jabber.org/protocol/offline",
				new OfflineMessageInfo.Provider());

		// Last Activity
		pm
				.addIQProvider("query", "jabber:iq:last",
						new LastActivity.Provider());

		// User Search
		pm
				.addIQProvider("query", "jabber:iq:search",
						new UserSearch.Provider());

		// SharedGroupsInfo
		pm.addIQProvider("sharedgroup",
				"http://www.jivesoftware.org/protocol/sharedgroup",
				new SharedGroupsInfo.Provider());

		// JEP-33: Extended Stanza Addressing
		pm.addExtensionProvider("addresses",
				"http://jabber.org/protocol/address",
				new MultipleAddressesProvider());

		// FileTransfer
		pm.addIQProvider("si", "http://jabber.org/protocol/si",
				new StreamInitiationProvider());

		pm.addIQProvider("query", "http://jabber.org/protocol/bytestreams",
				new BytestreamsProvider());

		// pm.addIQProvider("open", "http://jabber.org/protocol/ibb",
		// new IBBProviders.Open());
		//
		// pm.addIQProvider("close", "http://jabber.org/protocol/ibb",
		// new IBBProviders.Close());
		//
		// pm.addExtensionProvider("data", "http://jabber.org/protocol/ibb",
		// new IBBProviders.Data());

		// Privacy
		pm.addIQProvider("query", "jabber:iq:privacy", new PrivacyProvider());

		pm.addIQProvider("command", "http://jabber.org/protocol/commands",
				new AdHocCommandDataProvider());
		pm.addExtensionProvider("malformed-action",
				"http://jabber.org/protocol/commands",
				new AdHocCommandDataProvider.MalformedActionError());
		pm.addExtensionProvider("bad-locale",
				"http://jabber.org/protocol/commands",
				new AdHocCommandDataProvider.BadLocaleError());
		pm.addExtensionProvider("bad-payload",
				"http://jabber.org/protocol/commands",
				new AdHocCommandDataProvider.BadPayloadError());
		pm.addExtensionProvider("bad-sessionid",
				"http://jabber.org/protocol/commands",
				new AdHocCommandDataProvider.BadSessionIDError());
		pm.addExtensionProvider("session-expired",
				"http://jabber.org/protocol/commands",
				new AdHocCommandDataProvider.SessionExpiredError());
	}

}
